package com.doubi.common.config.springBoot;

import com.doubi.common.config.dfa.DFAException;
import com.doubi.common.config.expiry.ExpiryException;
import com.doubi.common.config.jwt.JwtException;
import com.doubi.vo.AppModel;
import com.doubi.vo.ErrorReturn;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.UnauthorizedException;
import org.springframework.beans.TypeMismatchException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import javax.validation.UnexpectedTypeException;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;

/**
 * MrDoubi
 * 2019年1月3日 18:33:23
 * 处理全局的错误
 */
@ControllerAdvice
@Slf4j
public class NullPointerExceptionHandler {

    @ExceptionHandler(Exception.class)
    @ResponseBody
    public ErrorReturn dealNullPointerException(Exception e) {
        if(e.getCause() instanceof  JwtException){
            return jwtException(e);
        }
        ErrorReturn error = new ErrorReturn();
        log.error("异常信息： ------ >" + e);
        error.setCode(-1);
        error.setMsg("操作失败，请稍后重试！");
        return error;
    }

    @ExceptionHandler(DFAException.class)
    @ResponseBody
    public ErrorReturn DFAException(DFAException e) {
        ErrorReturn error = new ErrorReturn();
        error.setCode(335);
        error.setMsg("包含敏感词汇，请检查后提交！");
        return error;
    }

    @ExceptionHandler(JwtException.class)
    @ResponseBody
    public ErrorReturn jwtException(Exception e) {
        ErrorReturn error = new ErrorReturn();
        error.setCode(401);
        error.setMsg("请先登录！！");
        return error;
    }

    @ExceptionHandler(ExpiryException.class)
    @ResponseBody
    public ErrorReturn expiryException(Exception e) {
        ErrorReturn error = new ErrorReturn();
        error.setCode(334);
        error.setMsg("请勿频繁提交！！");
        return error;
    }

    @ExceptionHandler(TypeMismatchException.class)
    @ResponseBody
    public ErrorReturn typeMismatchException(TypeMismatchException e) {
        ErrorReturn error = new ErrorReturn();
        error.setCode(400);
        error.setMsg("无法处理的参数！");
        return error;
    }
    /**
     * 全局验证 处理
     */
    @ExceptionHandler(ConstraintViolationException.class)
    @ResponseBody
    public ErrorReturn ConstraintViolationException(ConstraintViolationException e) {
        ErrorReturn error = new ErrorReturn();
        error.setCode(400);
        List<String> msgList = new ArrayList<>();
        for (ConstraintViolation<?> constraintViolation : e.getConstraintViolations()) {
            msgList.add(constraintViolation.getMessage());
        }
        String messages = StringUtils.join(msgList.toArray(), ";");
        error.setMsg(messages);
        return error;
    }

    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    @ResponseBody
    public ErrorReturn HttpException(Exception e) {
        ErrorReturn error = new ErrorReturn();
        error.setCode(402);
        error.setMsg("请先使用对应的请求方式！");
        return error;
    }

    @ExceptionHandler(Throwable.class)
    @ResponseBody
    public ErrorReturn dealThrowable(Throwable throwable) {
        ErrorReturn error = new ErrorReturn();
        log.error("操作异常： ------->  "+throwable);
        error.setMsg("操作失败，请稍后重试！");
        error.setCode(-1);
        return error;
    }

    /**
     * Mrdoubi
     * 2019年1月5日 17:11:17
     * 处理访问方法时权限不足问题  不会报错而是会返回一个无权限页面
     *
     * @param request req
     * @param e       异常
     * @return 无权限页面
     */
    @ExceptionHandler(value = UnauthorizedException.class)
    public String defaultErrorHandler(HttpServletRequest request, Exception e, HttpServletResponse response) {
        String method = request.getMethod();
        if ("GET".equals(method)) {
            return "web/error/notRole";
        } else {
            String mas = e.getMessage();
            mas = mas.split(" ")[mas.split(" ").length - 1];
            writeJsonData(response, new AppModel(-1, "您没有" + mas + "权限"));
        }
        return "web/error/notRole";
    }

    private void writeJsonData(HttpServletResponse response, Object data) {
        response.setContentType("application/json");
        PrintWriter out = null;
        JsonConfig config = new JsonConfig();
        try {
            response.setCharacterEncoding("UTF-8");
            out = response.getWriter();
            if (data instanceof List) {
                JSONArray array = JSONArray.fromObject(((List<?>) data).toArray(), config);
                out.print(array.toString());
            } else {
                String result = JSONObject.fromObject(data, config).toString();
                out.print(result);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
        }
    }


}